﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using Newtonsoft.Json;
using Model;

namespace WebApplication
{
    public class MapView : Map
    {
        public string MapCSS { get; set; }
        public string AreaTitleCSS { get; set; }
        public string AreaCtontentCSS { get; set; }
        public string WorkNodeGeneralCSS { get; set; }
        public string JsonData { get; private set; }
        public ProjectView ProjectData { get; private set; }
        public readonly Dictionary<NodeStatusEnum, string> NodeStatusCSS = new Dictionary<NodeStatusEnum, string>();

        public MapView(ProjectView project)
        {
            ProjectData = project;
        }

        public string GetActivityHtml()
        {
            StringBuilder sb = new StringBuilder();
            //var areas = this.Areas.OrderBy(x => x.Order);
            Areas.Sort(new Comparison<Area>((x, y) => { return x.Order.CompareTo(y.Order); }));

            int maxRow = 0;
            foreach (Area a in Areas)
            {
                if (a.Nodes.Count > maxRow)
                {
                    maxRow = a.Nodes.Count;
                }
            }

            sb.Append("<table class='" + MapCSS + "'>");
            sb.Append("<tr>");
            //sb.Append("<tr><th class='" + AreaTitleCSS + "'>阶段\\部门</th>");
            Areas.ForEach(x =>
            {
                sb.Append("<th class='" + AreaTitleCSS + "'>").Append(x.Name).Append("</th>");
            });
            sb.Append("</tr>");

            List<WorkNodeView> nodes = new List<WorkNodeView>();
            Areas.ForEach(x =>
            {
                x.Nodes.ForEach(n =>
                {
                    nodes.Add(new WorkNodeView(n));
                });
            });

            nodes = nodes.OrderBy(x => x.Order).ToList();
            int rowIndex = 1;
            nodes.ForEach(x =>
            {
                var area = Areas.FirstOrDefault(w => w.ID == x.AreaID);
                x.ColumnIndex = area.Order + 1;
                x.RowIndex = rowIndex;

                var nextNode = nodes.Where(w => x.NextNodeIDList.Contains(w.ID)).FirstOrDefault();
                if (nextNode != null)
                {
                    var area1 = Areas.FirstOrDefault(w => w.ID == nextNode.AreaID);
                    if (area1.Order <= area.Order)
                    {
                        rowIndex++;
                    }
                }
            });
            JsonData = JsonConvert.SerializeObject(nodes);
            for (int i = 1; i <= rowIndex; i++)
            {
                sb.Append("<tr>");
                //if (i == 1)
                //{
                //    sb.Append("<td class='NameTd' rowspan='" + (rowIndex) + "'><div class='Name'>" + this.Name + "</div></td>");
                //}
                Areas.ForEach(x =>
                {
                    var nodeList = nodes.Where(w => w.RowIndex == i && w.ColumnIndex == x.Order + 1).ToList();
                    sb.Append("<td>");
                    nodeList.ForEach(w =>
                    {
                        sb.Append("<div onclick='openPointDetails(\"" + w.ID + "\")' id='node_" + w.ID + "' class='" + WorkNodeGeneralCSS + " " + NodeStatusCSS[w.Status] + "'>" + w.Content + "</div>");
                    });
                    sb.Append("</td>");
                });
                sb.Append("</tr>");
            }
            sb.Append("</table>");
            return sb.ToString();
        }

        public string GetTimeHtml()
        {
            StringBuilder sb = new StringBuilder();
            //var areas = this.Areas.OrderBy(x => x.Order);
            Areas.Sort(new Comparison<Area>((x, y) => { return x.Order.CompareTo(y.Order); }));
            List<WorkNodeView> nodeList = new List<WorkNodeView>();
            List<DateTime> dates = new List<DateTime>();
            Areas.ForEach(x =>
            {
                x.Nodes.ForEach(n =>
                {
                    nodeList.Add(new WorkNodeView(n));
                    dates.Add(n.BeginDate.Value); dates.Add(n.EndDate.Value);
                });
            });

            int rowIndex = 0;
            foreach (Area a in Areas)
            {
                var nodes = nodeList.Where(w => w.AreaID == a.ID).OrderBy(b => b.BeginDate).ToList();
                if (nodes.Count == 0) { continue; }
                int rowCount = 1;
                nodes[0].RowIndex = rowIndex;
                for (int i = 1; i < nodes.Count; i++)
                {
                    if (nodes[i].BeginDate.Value <= nodes[i - 1].EndDate.Value)
                    {
                        rowCount++;
                        rowIndex++;
                    }
                    nodes[i].RowIndex = rowIndex;
                }
                a.RowCount = rowCount;
                rowIndex++;
            }

            dates.Sort();

            DateTime begin = dates.First();
            DateTime end = dates.Last();
            int columnCount = 0;
            while (true)
            {
                if (begin.CompareTo(end) > 0)
                {
                    break;
                }
                begin = begin.AddMonths(1);
                columnCount++;
            }


            sb.Append("<table border='1' class='" + MapCSS + "' style='width:" + (columnCount * 100 + 100) + "px'>");
            sb.Append("<tr><th class='" + AreaTitleCSS + "'>部门\\时间</th>");

            begin = this.ProjectData.Project.BeginDate.Value;
            for (int i = 0; i < columnCount; i++)
            {
                int dayCount = DateTime.DaysInMonth(begin.Year, begin.Month);
                sb.Append("<th days='" + dayCount + "' id='" + begin.ToString("yyyy_MM") + "' class='" + AreaTitleCSS + " TimeColumn'>").Append(begin.ToString("yyyy-MM")).Append("</th>");
                begin = begin.AddMonths(1);
            }

            sb.Append("</tr>");
            foreach (Area a in Areas)
            {
                if (a.RowCount == 1)
                {
                    sb.Append("<tr>");
                    sb.Append("<td class='" + AreaTitleCSS + "' id='" + a.ID + "'>" + a.Name + "</td>");
                    for (int j = 0; j < columnCount; j++)
                    {
                        sb.Append("<td></td>");
                    }
                    sb.Append("</tr>");
                }
                else
                {
                    sb.Append("<tr>");
                    sb.Append("<td rowspan='" + a.RowCount + "' class='" + AreaTitleCSS + "' id='" + a.ID + "'>" + a.Name + "</td>");
                    for (int j = 0; j < columnCount; j++)
                    {
                        sb.Append("<td></td>");
                    }

                    sb.Append("</tr>");
                    for (int i = 1; i < a.RowCount; i++)
                    {
                        sb.Append("<tr>");
                        for (int j = 0; j < columnCount; j++)
                        {
                            sb.Append("<td></td>");
                        }

                        sb.Append("</tr>");
                    }
                }

            }
            sb.Append("</table>");
            JsonData = JsonConvert.SerializeObject(nodeList);
            return sb.ToString();
        }
    }

    public class WorkNodeView : WorkNode
    {
        public int ColumnIndex { get; set; }
        public int RowIndex { get; set; }
        public string StatusString { get; set; }
        public int Days { get; set; }
        public string BeginDateID { get; set; }
        public string EndDateID { get; set; }
        public int BeginDayIndex { get; set; }
        public int EndDayIndex { get; set; }

        public WorkNodeView(WorkNode node)
        {
            this.AreaID = node.AreaID;
            this.ColumnIndex = 0;
            this.Content = node.Content;
            this.ID = node.ID;
            this.NextNodes.AddRange(node.NextNodes);
            this.Order = node.Order;
            this.RowIndex = 0;
            this.Status = node.Status;
            this.StatusString = this.Status.ToString();
            this.NextNodeIDList.AddRange(node.NextNodeIDList);
            this.BeginDate = node.BeginDate;
            this.EndDate = node.EndDate;
            Days = (int)(EndDate.Value - BeginDate.Value).TotalDays + 1;
            BeginDateID = this.BeginDate.Value.ToString("yyyy_MM");
            EndDateID = this.EndDate.Value.ToString("yyyy_MM");
            BeginDayIndex = BeginDate.Value.Day;
            EndDayIndex = EndDate.Value.Day;
        }
    }
}